#pragma once

#include "Utils.h"
#include "AbstractEntity.h"
#include "QuadTree.h"
#include "EffectManager.h"

class EntityInteractive {
public:
	static void interactWithGround(AbstractEntity* ground, AbstractEntity* dyObject, CollistionOutput* output) {
		Rect* rectGround = ground->getAbstractData()->getRect();
		Rect* rectDyObject = dyObject->getAbstractData()->getRect();
		if (output->normaly > 0 || (output->entryTime == 0 && rectDyObject->Vy < 0 && 
			( rectDyObject->getBottom() > rectGround->Y || dyObject->getAbstractData()->getType() == _ID_MAP_STAGE3_TANK_1 ||
			(dyObject->getAbstractData()->state == _DATA_CONTRA_STATE_IN_WATER && rectDyObject->Y > rectGround->getBottom())))) {
				// test scope
				rectDyObject->Y = rectGround->Y + rectGround->Height / 2 + rectDyObject->Height / 2;
				rectDyObject->Vy = -6;
				dyObject->updateData(ACTIONS_STOP_FLYING, 0);
		}
	}

	//Interact with item
	static void interactWithItem(AbstractEntity* item, AbstractEntity* dyObject, CollistionOutput* output) {
		if (dyObject->getAbstractData()->getType() == _ID_CONTRA) {
			item->updateData(ACTIONS_HIT_PLAYER, 0);
			item->updateData(ACTIONS_HIT_ITEM, item->getAbstractData()->getType());
			dyObject->updateData(ACTIONS_HIT_ITEM, item->getAbstractData()->getType());
		}
	}

	//Mai
	/*Add interact With Bridge*/
	static void interactWithBridge(AbstractEntity* bridge, AbstractEntity* dyObject, CollistionOutput* output)
	{
		Rect* rectGround = bridge->getAbstractData()->getRect();
		Rect* rectDyObject = dyObject->getAbstractData()->getRect();
		if (output->normaly > 0 || (output->entryTime == 0 && rectDyObject->Vy < 0 && 
			rectDyObject->getBottom() > rectGround->Y )) {
				rectDyObject->Y = rectGround->Y + rectGround->Height / 2 + rectDyObject->Height / 2;
				rectDyObject->Vy = -6;
				dyObject->getAbstractData()->updateData(ACTIONS_STOP_FLYING, 0);
		}
	}

	//Mai
	/*Add interact With Water*/
	static void interactWithWater(AbstractEntity* water, AbstractEntity* dyObject, CollistionOutput* output)
	{
		Rect* rectGround = water->getAbstractData()->getRect();
		Rect* rectDyObject = dyObject->getAbstractData()->getRect();
		if (output->normaly > 0 || (output->entryTime == 0 && rectDyObject->Vy < 0)) {
			if (dyObject->getAbstractData()->state != _DATA_CONTRA_STATE_WATER_LAND) {
				rectDyObject->Y = rectGround->Y + rectDyObject->Height / 3;
				rectDyObject->Vy = -6;
			} 

			dyObject->updateData(ACTIONS_IN_WATER, 0);
		}
	}

	/*Stone interact with ground*/
	static void interactStoneAndGround(AbstractEntity* stone, AbstractEntity* ground, CollistionOutput* output)
	{
		Rect* rectStone = stone->getAbstractData()->getRect();
		Rect* rectDyObject = ground->getAbstractData()->getRect();
		if(ground->getAbstractData()->getType() == _ID_MAP_STAGE1_GRASS_1)
		{
			if(output->normaly > 0 || (output->entryTime == 0 && rectDyObject->Vy < 0 && rectDyObject->getBottom() > rectStone->Y))
			{
				stone->updateData(ACTIONS_STONE_IN_LAND, 0);
			}
		}
	}

	/*interact with boom*/
	static void interactWithBoom(AbstractEntity* boom, AbstractEntity* dyObject, CollistionOutput* output)
	{
		Rect* rectBoom = boom->getAbstractData()->getRect();
		if(dyObject->getAbstractData()->getType() != _ID_MAP_STAGE3_BOOM_1)
		{
			boom->updateData(ACTIONS_BOOM_KILL, 0);
		}
	}

	/*interact with boss 3 items*/
	static void interactBoss3Items(AbstractEntity* bossItem, AbstractEntity* dyObject, CollistionOutput* output, int index)
	{
		Rect* rectStone = bossItem->getAbstractData()->getRect();
		Rect* rectDyObject = dyObject->getAbstractData()->getRect();
		if(dyObject->getAbstractData()->getType() == _ID_MAP_STAGE1_GRASS_1)
		{
			if(output->normaly > 0 || (output->entryTime == 0 && rectDyObject->Vy < 0 && rectDyObject->getBottom() > rectStone->Y))
			{
				bossItem->updateData(ACTIONS_BOSS3_ITEM_IN_LAND, index);
			}
		}
	}

	static void interactWithBoat(AbstractEntity* bridge, AbstractEntity* dyObject, CollistionOutput* output)
	{
		Rect* rectBoat = bridge->getAbstractData()->getRect();
		Rect* rectDyObject = dyObject->getAbstractData()->getRect();
		if (output->normaly > 0 || (output->entryTime == 0 && rectDyObject->Vy < 0 && rectDyObject->getBottom() > rectBoat->Y)) {
			rectDyObject->Y = rectBoat->Y + rectBoat->Height / 2 + rectDyObject->Height / 2;
			if(rectDyObject->Vx == 0)
			{
				rectDyObject->Vx = rectBoat->Vx;
			}
			rectDyObject->Vy = -6;

			dyObject->getAbstractData()->updateData(ACTIONS_STOP_FLYING, 0);
		}
	}

	static void interact(AbstractEntity* dyObject, CollistionOutput* output) {
		int type = output->object->getAbstractData()->getType();
		if (type == _ID_MAP_STAGE1_GRASS_1) {
			interactWithGround(output->object, dyObject, output);
		}
		//Mai
		//int type = output->object->getAbstractData()->getType();
		if(type == _TYPE_OBS_BRIDGE_LEFT_1 || type == _TYPE_OBS_BRIDGE_CENTER_1 || type == _TYPE_OBS_BRIDGE_RIGHT_1 || type == _ID_MAP_STAGE2_BRIDGE_1)
		{
			interactWithBridge(output->object, dyObject, output);
		}

		if(type == _ID_MAP_STAGE2_BOAT_1)
		{
			interactWithBoat(output->object, dyObject, output);
		}

		if(type == _ID_MAP_STAGE1_WATER_1 && dyObject->getAbstractData()->type == _ID_CONTRA)
		{
			interactWithWater(output->object, dyObject, output);
		}

		if (type == _ID_ITEM_1) {
			interactWithItem(output->object, dyObject, output);
		}

		if (dyObject->getAbstractData()->getType() == _ID_CONTRA && 
			(type == _ID_ARMY_RUNNING_SOLDIER || type == _ID_MAP_STAGE3_TANK_1 || type == _ID_MAP_STAGE2_STONE_1 || type == _ID_MAP_STAGE3_BOOM_1)) {
				dyObject->updateData(ACTIONS_IS_HURT, 0);
		}

		if (dyObject->getAbstractData()->getType() == _ID_CONTRA && 
			(type == _ID_MAP_STAGE3_BOOM_1)) {
				dyObject->updateData(ACTIONS_IS_HURT, 0);
				output->object->updateData( ACTIONS_BOOM_KILL, 0);
		}

		if (dyObject->getAbstractData()->getType() == _ID_CONTRA && 
			type == _ID_MAP_STAGE2_BRIDGE_1) {
				Rect* rect1 = output->object->getAbstractData()->subRect->at(0);
				Rect* rect2 = output->object->getAbstractData()->subRect->at(1);
				if (rect1->IsIntersectAll(rect1, dyObject->getAbstractData()->getRect()) || 
					rect2->IsIntersectAll(rect1, dyObject->getAbstractData()->getRect())) {
						dyObject->updateData(ACTIONS_IS_HURT, 0);
				}
		}
	}

	static void interactWithBulletArmy(ContraEntity* contra, CollistionOutput* output) {
		if (contra->getData()->undeadDelay > 0) return;
		contra->updateData(ACTIONS_IS_HURT, 0);
		output->object->updateData(ACTIONS_KILL_BULLET, 0);
	}

	static void interactWithBoss1(AbstractEntity* bullet, CollistionOutput* output) {
		AbstractEntity* boss1 = output->object;
		Rect* rect;
		Rect* bulletRect = bullet->getAbstractData()->getRect();
		for (int i = 0; i < boss1->getAbstractData()->subRect->size(); i++) {
			rect = boss1->getAbstractData()->subRect->at(i);

			if (bulletRect->IsIntersectAll(bulletRect, rect) && boss1->getSubEntity(i)->getAbstractData()->canInteract) {
				output->object->updateData(ACTIONS_IS_HURT, i * 10 + bullet->getAbstractData()->getType() - _ID_BULLET_LEVEL_0);
				bullet->updateData(ACTIONS_KILL_BULLET, 0);

				double x = rect->X - bulletRect->X;
				x = bulletRect->X + x / 2;
				double y = rect->Y - bulletRect->Y;
				y = bulletRect->Y + y / 2;
				if(bullet->getAbstractData()->type == _ID_BULLET_LEVEL_1) {
					EffectManager::getInstatnse()->createEffect(EffectType::TYPE_Bullet_Small_Fire, x, y);
				} else {
					EffectManager::getInstatnse()->createEffect(EffectType::TYPE_Bullet_Big_Fire, x, y);
				}
			}
		}
	}

	static void interactWithBulletPlayer(AbstractEntity* bullet, CollistionOutput *output, bool isBulletContra) {
		if (isBulletContra) {
			switch (output->object->getAbstractData()->getType()) {
			case _ID_ITEM_PACKAGE:
			case _ID_ITEM_BLOCK:
			case _ID_ARMY_RUNNING_SOLDIER:
				//case _ID_ARMY_BOSS_TOP_LEFT_1:
				//case _ID_ARMY_BOSS_TOP_RIGHT_1:
			case _ID_MAP_STAGE3_TANK_1:
			case _ID_MAP_STAGE3_GUN_ENEMY_1:
			case _ID_ARMY_RED_SOLDIER:
			case _ID_ARMY_RED_HIDDEN:
			case _ID_MAP_STAGE2_STONE_1:
			case _ID_MAP_STAGE2_WATER_ENEMY_1:
			case _ID_ARMY_GUN_2:
			case _ID_ARMY_GUN_1:
				//output->object->getAbstractData()->getRect()->Y += 100;
				bullet->updateData(ACTIONS_KILL_BULLET, 0);
				output->object->updateData(ACTIONS_IS_HURT, bullet->getAbstractData()->getType() - _ID_BULLET_LEVEL_0);
				double x = output->object->getAbstractData()->rect->X - bullet->getAbstractData()->getRect()->X;
				x = bullet->getAbstractData()->getRect()->X + x / 2;
				double y = output->object->getAbstractData()->rect->Y - bullet->getAbstractData()->getRect()->Y;
				y = bullet->getAbstractData()->getRect()->Y + y / 2;
				if(bullet->getAbstractData()->type == _ID_BULLET_LEVEL_1)
				{
					EffectManager::getInstatnse()->createEffect(EffectType::TYPE_Bullet_Small_Fire, 
						x, y);
				}
				else
				{
					EffectManager::getInstatnse()->createEffect(EffectType::TYPE_Bullet_Big_Fire, 
						x, y);
				}
			}
			if (output->object->getAbstractData()->getType() == _ID_ARMY_BOSS_1 ||
				output->object->getAbstractData()->getType() == _ID_MAP_STAGE3_BOSS_1) {
					interactWithBoss1(bullet, output);
			}	
		}
		if (!isBulletContra) {
			if (bullet->getAbstractData()->getType() % _ID_BULLET_BOSS_1 == 0) {
				if (output->object->getAbstractData()->getType() == _ID_MAP_STAGE1_GRASS_1) {
					if (bullet->getAbstractData()->getRect()->Y < 50) {
						EffectManager::getInstatnse()->createEffect(EffectType::TYPE_Object_Fire, 
							bullet->getAbstractData()->getRect()->X, bullet->getAbstractData()->getRect()->Y);
						bullet->updateData(ACTIONS_KILL_BULLET, 0);
					}
				}
			}
		}
	}


};